SpringCloud基于Nacos和Eureka 实现双注册双订阅模式,可用于将注册中心Eureka平滑过渡到Nacos的解决方案

您所在的位置:网站首页 eurka nacos SpringCloud基于Nacos和Eureka 实现双注册双订阅模式,可用于将注册中心Eureka平滑过渡到Nacos的解决方案

SpringCloud基于Nacos和Eureka 实现双注册双订阅模式,可用于将注册中心Eureka平滑过渡到Nacos的解决方案

2024-07-12 07:09| 来源: 网络整理| 查看: 265

前言 大概在去年的时候发现生产环境使用eureka经常会发现服务假死eureka没有给踢掉的情况,然后就衍生了要不就换个注册中心试试,然后就了解到了nacos,正好他还融合了配置中心,但是后来碍于切换时怕生产环境不稳定,丢数据等问题就一直没有换,但后续的项目的注册中心都换成了nacos,这篇文章我就来模拟一下如何将eureka平滑切换成nacos 父工程构建 这里我在父工程里边又单独创建了一层父工程,我分别在alibaba-cloud 、netflix-cloud 中模拟新旧微服务 在这里插入图片描述 父工程pom 4.0.0 top.fate nacoAndEureka pom 1.0.0 netflix-cloud alibaba-cloud 模拟旧版微服务 netflix-cloud pom如下 ,因为这里是模拟旧服务,所以都采用旧版本 nacoAndEureka top.fate 1.0.0 4.0.0 netflix-cloud pom eureka eureka-provider eureka-consumer 2.1.2.RELEASE Greenwich.SR5 org.springframework.boot spring-boot-dependencies ${spring.boot.version} pom import org.springframework.cloud spring-cloud-dependencies ${spring.cloud.version} pom import 搭建eureka

在这里插入图片描述

pom依赖如下 netflix-cloud top.fate 1.0.0 4.0.0 eureka org.springframework.cloud spring-cloud-starter-netflix-eureka-server EurekaApplication 启动类 package top.fate.eureka; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @EnableEurekaServer @SpringBootApplication public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } } application.yml server: port: 8761 spring: application: name: eureka-service eureka: instance: # 设置该服务注册中心的hostname hostname: 127.0.0.1 client: # 我们创建的是服务注册中心,而不是普通的应用,这个应用会向注册中心注册它自己 #,设置为false就是禁止自己向自己注册的这个种行为 register-with-eureka: false # 不去检索其他的服务,因为注册中心本身的职责就是维护服务实例 fetch-registry: false # 制定服务注册中心的位置 service-url.defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ eureka-provider

在这里插入图片描述

pom依赖如下 netflix-cloud top.fate 1.0.0 4.0.0 eureka-provider 8 8 org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-netflix-eureka-client EurekaProviderApplication 启动类 package top.fate.eurekaprovider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @auther:Wangxl * @Emile:[email protected] * @Time:2022/6/16 14:23 */ @SpringBootApplication @EnableEurekaClient @RestController public class EurekaProviderApplication { public static void main(String[] args) { SpringApplication.run(EurekaProviderApplication.class, args); } @GetMapping("/info") public String info(){ return "this is eureka-service"; } } application.yml server: port: 8081 spring: application: name: provider eureka: client: service-url: defaultZone: "http://localhost:8761/eureka" eureka-consumer

在这里插入图片描述

pom依赖如下 netflix-cloud top.fate 1.0.0 4.0.0 eureka-consumer org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-netflix-eureka-client io.github.openfeign feign-httpclient org.springframework.cloud spring-cloud-starter-openfeign EurekaConsumerApplication 启动类 package top.fate.eurekaconsumer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; import top.fate.eurekaconsumer.client.EurekaProviderClient; /** * @auther:Wangxl * @Emile:[email protected] * @Time:2022/6/16 14:43 */ @SpringBootApplication @EnableEurekaClient @EnableFeignClients(clients = EurekaProviderClient.class) public class EurekaConsumerApplication { public static void main(String[] args) { SpringApplication.run(EurekaConsumerApplication.class, args); } } EurekaProviderClient package top.fate.eurekaconsumer.client; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; /** * @auther:Wangxl * @Emile:[email protected] * @Time:2022/6/16 14:48 */ @FeignClient(value = "provider") public interface EurekaProviderClient { @GetMapping("info") String info(); } ConsumerController package top.fate.eurekaconsumer.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import top.fate.eurekaconsumer.client.EurekaProviderClient; import javax.annotation.Resource; /** * @auther:Wangxl * @Emile:[email protected] * @Time:2022/6/16 14:48 */ @RestController public class ConsumerController { @Resource private EurekaProviderClient eurekaProviderClient; @GetMapping("getProvider") public String getProvider(){ return eurekaProviderClient.info(); } } 测试服务是否可以调通 在这里插入图片描述 在这里插入图片描述

这里我三个服务都启动正常,直接访问8091consumer测试 ,如下图所示consumer 可以访问provider在这里插入图片描述

第一阶段流程图

在这里插入图片描述

模拟新版微服务 alibaba-cloud pom如下,采用最新版技术栈 nacoAndEureka top.fate 1.0.0 4.0.0 alibaba-cloud pom nacos-consumer nacos-provider 2.6.3 2021.0.1 2021.0.1.0 org.springframework.boot spring-boot-dependencies ${spring.boot.version} pom import org.springframework.cloud spring-cloud-dependencies ${spring.cloud.version} pom import com.alibaba.cloud spring-cloud-alibaba-dependencies ${spring.cloud.alibaba.version} 启动安装nacos

可以参考SpringCloudAlibaba篇(二)整合Nacos注册配置中心 这篇文章我就不重复操作了

nacos-provider pom 依赖 alibaba-cloud top.fate 1.0.0 4.0.0 nacos-provider org.springframework.boot spring-boot-starter-web com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery 2021.0.1.0 org.springframework.cloud spring-cloud-starter-netflix-eureka-client NacosProviderApplication 启动类 package top.fate.nacosprovider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; /** * @auther:Wangxl * @Emile:[email protected] * @Time:2022/6/16 16:55 */ @SpringBootApplication @RestController @EnableConfigurationProperties(AutoServiceRegistrationProperties.class) public class NacosProviderApplication { public static void main(String[] args) { SpringApplication.run(NacosProviderApplication.class, args); } @GetMapping("/info") public String info() { return "this is nacos-service"; } } application.properties spring.autoconfigure.exclude=org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration application.yml url: nacos: localhost:8848 server: port: 8082 spring: application: name: provider profiles: active: dev cloud: nacos: discovery: #集群环境隔离 cluster-name: shanghai #命名空间 namespace: ${spring.profiles.active} #持久化实例 ture为临时实例 false为持久化实例 临时实例发生异常直接剔除, 而持久化实例等待恢复 ephemeral: true #注册中心地址 server-addr: ${url.nacos} eureka: client: service-url: defaultZone: "http://localhost:8761/eureka" nacos-consumer pom依赖 alibaba-cloud top.fate 1.0.0 4.0.0 nacos-consumer org.springframework.boot spring-boot-starter-web com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery 2021.0.1.0 org.springframework.cloud spring-cloud-starter-netflix-eureka-client io.github.openfeign feign-httpclient org.springframework.cloud spring-cloud-starter-openfeign NacosConsumerApplication 启动类 package top.fate.nacosconsumer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationProperties; import org.springframework.cloud.openfeign.EnableFeignClients; import top.fate.nacosconsumer.client.EurekaProviderClient; import top.fate.nacosconsumer.client.NacosProviderClient; import top.fate.nacosconsumer.client.ProviderClient; /** * @auther:Wangxl * @Emile:[email protected] * @Time:2022/6/16 16:39 */ @SpringBootApplication @EnableFeignClients(clients = {EurekaProviderClient.class, NacosProviderClient.class, ProviderClient.class}) @EnableConfigurationProperties(AutoServiceRegistrationProperties.class) public class NacosConsumerApplication { public static void main(String[] args) { SpringApplication.run(NacosConsumerApplication.class, args); } } ProviderClient package top.fate.nacosconsumer.client; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; /** * @auther:Wangxl * @Emile:[email protected] * @Time:2022/6/16 18:24 */ @FeignClient(value = "provider") public interface ProviderClient { @GetMapping("info") String info(); } ConsumerController package top.fate.nacosconsumer.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import top.fate.nacosconsumer.client.ProviderClient; import javax.annotation.Resource; /** * @auther:Wangxl * @Emile:[email protected] * @Time:2022/6/16 14:48 */ @RestController public class ConsumerController { @Resource private ProviderClient providerClient; @GetMapping("getProvider") public String getProvider(){ return providerClient.info(); } } application.properties spring.autoconfigure.exclude=org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration application.yml url: nacos: localhost:8848 server: port: 8092 spring: application: name: nacos-consumer profiles: active: dev cloud: nacos: discovery: #集群环境隔离 cluster-name: shanghai #命名空间 namespace: ${spring.profiles.active} #持久化实例 ture为临时实例 false为持久化实例 临时实例发生异常直接剔除, 而持久化实例等待恢复 ephemeral: true #注册中心地址 server-addr: ${url.nacos} eureka: client: service-url: defaultZone: "http://localhost:8761/eureka" 上线双注册双订阅新provider服务 先启动nacosProviderApplication 在这里插入图片描述

如下图所示,我们已经实现了双注册,nacos和eureka中都注册了服务

nacos在这里插入图片描述

eureka 在这里插入图片描述 平滑切换注册中心 验证旧consumer

这里我访问8091的旧版Netflix客户端也就是eureka-consumer,看一下调用的是8081 eureka 还是8082 nacos , 这里我反复调用了十几次,返回结果为

this is nacos-service this is eureka-service

因为此时我们的8091客户端只有eurekaClient,然后我们的provider在eureka注册中心有两个实例,所以就触发了负载均衡,这里我们用的默认轮询模式,当前流程如下图

在这里插入图片描述

下线旧provider 现在我们就可以陆续开始平滑 切换注册中心了,旧provider可以关掉了,关掉旧provider之后此时的流程就如下图所示了 在这里插入图片描述

此时我们再访问旧consumer只会返回 this is nacos-service,因为旧的provider已经下线了 ,新provider当前已经切换完成!在这里插入图片描述

上线双注册双订阅新consumer服务,下线旧consumer 启动nacoConsumerApplication 在这里插入图片描述 访问8092验证是否能正常访问,继续访问getProvider接口,如下图所示访问正常,然后我们就可以下线旧consumer服务了 在这里插入图片描述 在这里插入图片描述 疑惑 (该步骤可以直接略过)

现在我们有个疑惑,现在有两个注册中心,服务发现是走的eureka还是nacos呢为此,我做了个实验,我分别启动了 旧provider、新provider、新consumer 此时双注册中心的服务

eureka provider8081、provider8082 consumer8092 nacos provider8082 consumer8092

现在我通过consumer8092客户端去请求,得到的结果只有 this is nacos-service ,因此判断注册中心默认走的是nacos.因为走nacos只会返回this is nacos-service, nacos只有一个实例。如果走eureka的话会轮询返回this is nacos-service、this is eureka-service ,eureka有两个实例。

此时的流程图 虚线代表该线路空闲

在这里插入图片描述

这里我找了下源码CompositeDiscoveryClient,调用的时候打了断点,发现系统创建了三个discoveryClient ,nacos排在第一个,如果可用的话直接就返回了 ,所以可以理解为默认走的是nacos在这里插入图片描述这里我想到了nacos有个服务下线功能,如果我将nacos中的服务下线之后应该就会去走eureka了吧在这里插入图片描述等待几秒过后,通过consumer8092客户端去请求,得到了我想要的结果分别轮询返回了 this is nacos-service、this is eureka-service,证明已经走eureka了

此时流程图虚线代表该线路空闲在这里插入图片描述 最后

此时我们生产上边是 新consumer、新provider、eureka、nacos,既然我们要切换到nacos,那eureka就也要停掉了,我们可以在下一版的服务中去掉 eureka的依赖和配置,只留下nacos,将这一个新版本部署上去之后就可以停掉eureka了

如下图所示

在这里插入图片描述

注意 如果直接引入eureka-client和nacos-client 会报错,如下 Field autoServiceRegistration in org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration required a single bean, but 2 were found: - nacosAutoServiceRegistration: defined by method 'nacosAutoServiceRegistration' in class path resource [com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.class] - eurekaAutoServiceRegistration: defined by method 'eurekaAutoServiceRegistration' in class path resource [org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.class] 需要在配置文件添加如下内容 spring.autoconfigure.exclude=org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration 启动类添加注解 @EnableConfigurationProperties(AutoServiceRegistrationProperties.class) 原创不易,请点个赞再走吧!感谢


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3